/**
 * @Project: Runer
 * @Title: XmppImpl.java
 * @Package com.runlooker.runer.xmpp
 * @author YINENG
 * @date 2014-7-18 上午10:08:56
 * @Copyright: 2014 www.yineng.com.cn Inc. All rights reserved.
 * @version V1.0
 */
package com.runlooker.runer.asmack;

import java.io.File;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;

import org.jivesoftware.smack.AccountManager;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterGroup;
import org.jivesoftware.smack.RosterListener;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Message.Type;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.sasl.SASLPlainMechanism;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.ConfigureProviderManager;
import org.jivesoftware.smackx.Form;
import org.jivesoftware.smackx.ReportedData;
import org.jivesoftware.smackx.ReportedData.Row;
import org.jivesoftware.smackx.ServiceDiscoveryManager;
import org.jivesoftware.smackx.filetransfer.FileTransfer.Status;
import org.jivesoftware.smackx.filetransfer.FileTransferListener;
import org.jivesoftware.smackx.filetransfer.FileTransferManager;
import org.jivesoftware.smackx.filetransfer.FileTransferRequest;
import org.jivesoftware.smackx.filetransfer.IncomingFileTransfer;
import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer;
import org.jivesoftware.smackx.packet.VCard;
import org.jivesoftware.smackx.receipts.DeliveryReceipt;
import org.jivesoftware.smackx.receipts.DeliveryReceiptManager;
import org.jivesoftware.smackx.receipts.DeliveryReceiptRequest;
import org.jivesoftware.smackx.receipts.ReceiptReceivedListener;
import org.jivesoftware.smackx.search.UserSearchManager;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Handler;

import com.alibaba.fastjson.JSON;
import com.runlooker.runer.application.MyApplication;
import com.runlooker.runer.dao.ChatMsgDao;
import com.runlooker.runer.dao.PresenceDao;
import com.runlooker.runer.dao.RosterEntryDao;
import com.runlooker.runer.entity.ChatMsgEntity;
import com.runlooker.runer.entity.LocalRosterEntity;
import com.runlooker.runer.entity.PersonInfoEntity;
import com.runlooker.runer.entity.PresenceEntity;
import com.runlooker.runer.queue.PresenceQueue;
import com.runlooker.runer.queue.RecivedMessageQueue;
import com.runlooker.runer.service.XmppService;
import com.runlooker.runer.ui.chat.FileDescriptionEntity;
import com.runlooker.runer.ui.rigister.RegisterActivity;
import com.runlooker.runer.util.EncryptionUtils;
import com.runlooker.runer.util.FileUtil;
import com.runlooker.runer.util.GZIPUtil;
import com.runlooker.runer.util.ImageUtil;
import com.runlooker.runer.util.JidUtil;
import com.runlooker.runer.util.L;
import com.runlooker.runer.util.NetworkUtil;
import com.runlooker.runer.util.PhoneInfoUtil;
import com.runlooker.runer.util.SDCardUtil;
import com.runlooker.runer.util.TimeUtil;

/**
 * @ClassName XmppImpl
 * @Description 模块描述
 * @author town
 * @Date 2014-7-18
 */
public class AsmackImpl implements Asmack {

	private static final String tag = AsmackImpl.class.getSimpleName();
	private static final String KEY = "runerbil";

	/**
	 * JID中的资源名称：资源/来源，用于区别客户端来源，xmpp协议设计为可多客户端同时登陆， resource就是用于区分同一用户不同端登陆
	 */
	public static final String JID_RESOUCE = "mobile";

	private static AsmackImpl mAsmackImpl;
	private XMPPConnection connection;

	private Roster mRoster;// 联系人对象
	private XmppService mXmppService;// 主服务

	private ConnectionListener mConnectionListener;// 连接监听
	private PacketListener mMessageListener;// 消息监听
	private PacketListener mIQListener;// 消息监听
	private RosterListener mRosterListener;// 联系人动态监听
	private PacketListener mPongListener;// ping 服务器动态监听
	private PacketListener mPresenceListener;// ping 服务器动态监听
	private FileTransferListener mFileTransferListener;// 文件传输监听
	private ReceiptReceivedListener mReceiptReceivedListener;// 消息回执监听

	private RosterEntryDao mRosterEntryDao;
	private PresenceDao mPresenceDao;
	private ChatMsgDao mChatMsgDao;
	private Long mLastReceivePacketTime;// 最新收到服务器发送到客户端的packet的时间（毫秒）

	public Long getLastReceivePacketTime() {
		return mLastReceivePacketTime;
	}

	// 加载此类，asmack会处理自动重连操作
	static {
		try {
			Class.forName("org.jivesoftware.smack.ReconnectionManager");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private ConnectionConfiguration mConfig;

	private Thread mGetRosterThread;

	private PresenceQueue mPresenceQueue = new PresenceQueue();// 处理出席信息的队列
	private RecivedMessageQueue mMessageQueue = new RecivedMessageQueue();// 处理消息的队列
	private Handler handler = new Handler() {

		@Override
		public void handleMessage(android.os.Message msg) {
			super.handleMessage(msg);
			switch (msg.what) {
			case MyApplication.SUCCESS:
				mXmppService.rosterChange();
				break;
			default:
				break;
			}
		}

	};

	private AsmackImpl(XmppService mXmppService) {
		this.mXmppService = mXmppService;

		mRosterEntryDao = new RosterEntryDao(mXmppService);
		mPresenceDao = new PresenceDao(mXmppService);
		mChatMsgDao = new ChatMsgDao(mXmppService);
		// 配置provider
		ConfigureProviderManager.configureProviderManager();

		{// 默认的配置有错误，手工配置消息回执provider
			ProviderManager pm = ProviderManager.getInstance();
			pm.addExtensionProvider(DeliveryReceipt.ELEMENT,
					DeliveryReceipt.NAMESPACE, new DeliveryReceipt.Provider());
			pm.addExtensionProvider(DeliveryReceiptRequest.ELEMENT,
					DeliveryReceipt.NAMESPACE,
					new DeliveryReceiptRequest.Provider());
			SASLAuthentication.registerSASLMechanism("PLAIN",
					SASLPlainMechanism.class);
			SASLAuthentication.supportSASLMechanism("PLAIN");
		}
		mConfig = new ConnectionConfiguration(MyApplication.SERVER_IP,
				MyApplication.PORT);
		/** 是否启用安全验证 */
		mConfig.setSendPresence(true);
		/** 是否允许重新连接 */
		mConfig.setReconnectionAllowed(true);
		mConfig.setSecurityMode(SecurityMode.enabled);
		mConfig.setCompressionEnabled(true);
		if (Build.VERSION.SDK_INT >= 14) {
			mConfig.setTruststoreType("AndroidCAStore");
			mConfig.setTruststorePassword(null);
			mConfig.setTruststorePath(null);
		} else {
			mConfig.setTruststoreType("BKS");
			String path = System.getProperty("javax.net.ssl.trustStore");
			if (path == null)
				path = System.getProperty("java.home") + File.separator + "etc"
						+ File.separator + "security" + File.separator
						+ "cacerts.bks";
			mConfig.setTruststorePath(path);
		}
		mConfig.setSASLAuthenticationEnabled(true);
		/** 是否启用调试 */
		mConfig.setDebuggerEnabled(true);
		connection = new XMPPConnection(mConfig);

		// ServiceDiscoveryManager sdm = ServiceDiscoveryManager
		// .getInstanceFor(connection);
		// if (sdm == null)
		// sdm = new ServiceDiscoveryManager(connection);
		// sdm.addFeature("http://jabber.org/protocol/disco#info");
		// sdm.addFeature("http://jabber.org/protocol/disco#item");
		// // 对于ServiceDiscoveryManager，需要加上muc协议
		// sdm.addFeature("http://jabber.org/protocol/muc");

		// 启动出席信息和消息队列线程，加强吞吐量
		mPresenceSaveThread.start();
		mMessageSaveThread.start();

		mLastReceivePacketTime = System.currentTimeMillis();

		ServiceDiscoveryManager sdm = ServiceDiscoveryManager
				.getInstanceFor(connection);
		if (sdm == null)
			sdm = new ServiceDiscoveryManager(connection);
		sdm.addFeature("http://jabber.org/protocol/disco#info");
		sdm.addFeature("jabber:iq:privacy");

		Roster.setDefaultSubscriptionMode(Roster.SubscriptionMode.accept_all);
	}

	public synchronized static AsmackImpl getInstance(XmppService mXmppService) {
		if (mAsmackImpl == null) {
			mAsmackImpl = new AsmackImpl(mXmppService);
		}
		return mAsmackImpl;
	}

	@Override
	public synchronized void register(String account, String password,
			Map<String, String> attributes) throws Exception {
		if (connection.isConnected()) {
			connection.disconnect();
		}
		String encodePasswordString = EncryptionUtils.encrypt(password, KEY);
		connection.connect();
		AccountManager amgr = connection.getAccountManager();
		amgr.createAccount(account, encodePasswordString, attributes);
		connection.login(account, encodePasswordString, JID_RESOUCE);
		// 注册成功后，登录并将本地手机信息和用户信息传递到服务器
		PersonInfoEntity entity = new PersonInfoEntity();
		entity.setAccount(account);
		entity.setEmail(attributes.get(RegisterActivity.EMAIL_KEY));
		entity.setNickName(attributes.get(RegisterActivity.NAME_KEY));
		savePersonInfo(entity);
		logout();
		connection.disconnect();
	}

	@Override
	public synchronized void login(final String account, final String password)
			throws Exception {

		logout();
		connection.connect();
		String encodePasswordString = EncryptionUtils.encrypt(password, KEY);
		connection.login(account, encodePasswordString, JID_RESOUCE);
		Presence presence = new Presence(Presence.Type.available);
		connection.sendPacket(presence);
		initSendMsgListener();// 与服务器交互消息监听,发送消息需要回执，判断是否发送成功
		registerRosterListener();// 监听联系人动态变化
		registerIQListener();// 注册IQ信息包监听
		registerMessageListener();// 注册消息监听
		registerFileReceivedListener();// 文件传输监听
		registerConnectionListener();// 连接监听
		registerPresenceListener();// 请求添加好友和被请求添加好友的信息监听
		sendOfflineMessages();// 发送离线消息、离线语音
		makeDir();
	}

	/**
	 * 注册IQ消息包监听
	 */
	private void registerIQListener() {
		if (mIQListener != null)
			connection.removePacketListener(mIQListener);
		PacketTypeFilter filter = new PacketTypeFilter(IQ.class);
		mIQListener = new PacketListener() {
			public void processPacket(Packet packet) {
				if (packet instanceof IQ) {
					mLastReceivePacketTime = System.currentTimeMillis();
				}
			}
		};
		connection.addPacketListener(mIQListener, filter);
	}

	private void registerFileReceivedListener() {
		FileTransferManager mFileTransferManager = new FileTransferManager(
				connection);
		if (mFileTransferListener != null) {
			mFileTransferManager
					.removeFileTransferListener(mFileTransferListener);
		}
		mFileTransferListener = new FileTransferListener() {

			@Override
			public void fileTransferRequest(FileTransferRequest request) {
				// 有SD卡，才接收图片
				if (SDCardUtil.isExistSDCard()) {
					makeDir();
					String filePath = null;
					IncomingFileTransfer transfer = request.accept();
					ChatMsgEntity entity = new ChatMsgEntity();
					entity.setDescription(request.getDescription());
					FileDescriptionEntity fileEntity = JSON.parseObject(
							entity.getDescription(),
							FileDescriptionEntity.class);
					entity.setMsgType(fileEntity.getFileType());
					entity.setChatType(fileEntity.getChatType());
					entity.setFileName(UUID.randomUUID() + ".jpg");
					switch (entity.getMsgType()) {
					case ChatMsgEntity.RECORD_FILE:
						filePath = MyApplication.getVoiceSavePath()
								+ entity.getFileName();
						break;
					case ChatMsgEntity.IAMGE_FILE:
						filePath = MyApplication.getImageSavePath()
								+ entity.getFileName();

						break;
					default:
						break;
					}
					File file = new File(filePath);
					entity.setPath(filePath);
					entity.setChatAccount(JidUtil.getAccountFromJID(request
							.getRequestor()));
					entity.setMessage("");
					entity.setPacketId(request.getStreamID());
					entity.setIsReaded(ChatMsgEntity.IS_NOT_READ);
					entity.setIsSended(ChatMsgEntity.SENDED_SUCCESS);
					entity.setMsgSourse(ChatMsgEntity.IS_COME_MSG);
					entity.setMsgType(fileEntity.getFileType());
					entity.setChatType(ChatMsgEntity.PERSON_CHAT);
					entity.setTime(TimeUtil.getCurrentMillisecond());
					(new ReciveFileStatusThread(entity, transfer, mXmppService))
							.start();
					try {
						transfer.recieveFile(file);
					} catch (XMPPException e) {
						e.printStackTrace();
					}

				}
			}
		};
		mFileTransferManager.addFileTransferListener(mFileTransferListener);
	}

	/**
	 * 创建应用文件夹
	 */
	private void makeDir() {
		FileUtil.mkdir(MyApplication.getImageSavePath());
		FileUtil.mkdir(MyApplication.getPortraitSavePath());
		FileUtil.mkdir(MyApplication.getVoiceSavePath());
	}

	public void sendFile(ChatMsgEntity entity) throws XMPPException {
		makeDir();
		L.i("ChatActivity", "filename3:   " + entity.getFileName());
		FileTransferManager sendFilemanager = new FileTransferManager(
				connection);
		OutgoingFileTransfer sendTransfer = sendFilemanager
				.createOutgoingFileTransfer(JidUtil.getJIDByAccount(
						entity.getChatAccount(), connection.getServiceName(),
						JID_RESOUCE));
		(new SendFileStatusThread(sendTransfer, mXmppService, entity)).start();
		FileDescriptionEntity fileEntity = new FileDescriptionEntity();
		fileEntity.setFileType(entity.getMsgType());
		fileEntity.setChatType(entity.getChatType());
		entity.setDescription(JSON.toJSONString(fileEntity));
		entity.setPacketId(sendTransfer.getStreamID());

		mChatMsgDao.saveOrUpdate(entity);
		if (entity.getMsgType() == ChatMsgEntity.IAMGE_FILE) {

			String tempPath = MyApplication.getTempPath()
					+ entity.getFileName();
			File file = new File(tempPath);
			if (file.exists()) {
				file.delete();
			}
			Bitmap bitmap = BitmapFactory.decodeFile(entity.getPath());
			Bitmap bitmap2 = ImageUtil.scaleToFit(bitmap, mXmppService);
			ImageUtil.savePNG_After(bitmap2, tempPath);

			// 压缩图片成功，则发送压缩后的图，否则发送原图
			if (FileUtil.getFileOrFilesSize(tempPath, FileUtil.SIZETYPE_KB) > 0) {
				sendTransfer.sendFile(new java.io.File(tempPath),
						entity.getDescription());
			} else {
				sendTransfer.sendFile(new java.io.File(entity.getPath()),
						entity.getDescription());
			}
		} else {
			sendTransfer.sendFile(new java.io.File(entity.getPath()),
					entity.getDescription());
		}
	}

	class ReciveFileStatusThread extends Thread {
		private IncomingFileTransfer transfer;
		private XmppService xmppService;
		private ChatMsgEntity entity;

		public ReciveFileStatusThread(ChatMsgEntity entity,
				IncomingFileTransfer tf, XmppService xmppService) {
			this.transfer = tf;
			this.xmppService = xmppService;
			this.entity = entity;

		}

		public void run() {
			while (!transfer.isDone()) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

			// 接收完成，才保存数据，回调接口
			if (transfer.getStatus() == Status.complete) {
				// 成功发送，则删除临时文件
				FileUtil.delFile(MyApplication.getTempPath()
						+ entity.getFileName());
				mChatMsgDao.saveOrUpdate(entity);
				xmppService.reciveFileStatus(entity, transfer.getStatus());
			}

		}
	}

	class SendFileStatusThread extends Thread {
		private OutgoingFileTransfer transfer;
		private XmppService xmppService;
		private ChatMsgEntity entity;

		public SendFileStatusThread(OutgoingFileTransfer tf,
				XmppService xmppService, ChatMsgEntity entity) {
			this.transfer = tf;
			this.xmppService = xmppService;
			this.entity = entity;
		}

		public void run() {
			L.i(tag, "启动发送线程");
			while (!transfer.isDone()) {
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

			if (transfer.getStatus() == Status.complete) {
				entity.setIsSended(ChatMsgEntity.SENDED_SUCCESS);
			} else {
				entity.setIsSended(ChatMsgEntity.SENDED_FAILED);
			}
			// 清空临时文件
			// FileUtil.delFile(MyApplication.TEMP_PATH + entity.getFileName());
			mChatMsgDao.saveOrUpdate(entity);
			xmppService.sendFileStatus(entity, transfer.getStatus());
			L.i(tag, "结束发送线程");
		}
	}

	// unavailable -- 通知实体将不可通信.
	// subscribe -- 发送者希望订阅接收者的出席信息.
	// subscribed -- 发送者允许接收者接收他们的出席信息.
	// unsubscribe -- 发送者取消订阅另一个实体的出席信息.
	// unsubscribed -- 订阅者的请求被拒绝或以前的订阅被取消.
	// probe -- 对一个实体当前的出席信息的请求; 只应(SHOULD)由服务器代替一个用户生成.
	// error -- 处理或递送之前发送的出席信息节的时候发生了错误.
	private void registerPresenceListener() {
		if (mPresenceListener != null) {
			connection.removePacketListener(mPresenceListener);
		}

		// 理解为条件过滤器 过滤出Presence包
		PacketFilter filter = new AndFilter(
				new PacketTypeFilter(Presence.class));
		mPresenceListener = new PacketListener() {

			@Override
			public void processPacket(Packet packet) {
				mLastReceivePacketTime = System.currentTimeMillis();
				if (packet instanceof Presence) {
					Presence presence = (Presence) packet;

					// 只处理订阅信息
					if (presence.getType().equals(Presence.Type.subscribe)
							|| presence.getType().equals(
									Presence.Type.subscribed)
							|| presence.getType().equals(
									Presence.Type.unsubscribe)
							|| presence.getType().equals(
									Presence.Type.unsubscribed)) {

						PresenceEntity entity = new PresenceEntity();
						if (presence.getFrom() != null) {
							entity.setFromAccount(JidUtil
									.getAccountFromJID(presence.getFrom()));
							if (!MyApplication.isSelf(mXmppService,
									entity.getFromAccount())) {
								entity.setPrecenceType(PresenceEntity
										.parsetype(presence.getType()));
								mPresenceQueue.putPresenceEntity(entity);
							}
						}

					}
				}
			}
		};
		connection.addPacketListener(mPresenceListener, filter); // 注册监听
	}

	// 保存出席信息到本地的线程
	private Thread mPresenceSaveThread = new Thread(new Runnable() {
		@Override
		public void run() {
			while (true) {
				PresenceEntity entity = mPresenceQueue.getPresenceEntity();
				mPresenceDao.saveOrUpdateEntity(entity);
				mXmppService.precenceChange(entity);
			}
		}
	});

	private void registerConnectionListener() {
		if (mConnectionListener != null) {
			connection.removeConnectionListener(mConnectionListener);
		}
		mConnectionListener = new ConnectionListener() {

			@Override
			public void reconnectionSuccessful() {// 成功重连服务器
				mXmppService.postConnectionScuessed();
			}

			@Override
			public void reconnectionFailed(Exception arg0) {// 试图连接服务器失败
				mXmppService.postConnectionFailed(arg0.getMessage());
			}

			@Override
			public void reconnectingIn(int arg0) {

			}

			@Override
			public void connectionClosedOnError(Exception arg0) {// 因为异常原因关闭连接
				mXmppService.postConnectionFailed(arg0.getMessage());
			}

			@Override
			public void connectionClosed() {// 连接关闭，或者重新连接的进程终止(正常关闭)
				mXmppService.postConnectionFailed("连接关闭！");
			}
		};
		connection.addConnectionListener(mConnectionListener);

	}

	/**
	 * 发送、或者接收到消息的监听
	 * 
	 * @Title: registerMessageListener
	 * @Description: 方法描述
	 */
	private void registerMessageListener() {
		if (mMessageListener != null)
			connection.removePacketListener(mMessageListener);

		PacketTypeFilter filter = new PacketTypeFilter(Message.class);

		mMessageListener = new PacketListener() {
			public void processPacket(Packet packet) {
				try {
					if (packet instanceof Message) {
						mLastReceivePacketTime = System.currentTimeMillis();
						Message msg = (Message) packet;
						if (Type.chat == msg.getType()) {
							ChatMsgEntity entity = new ChatMsgEntity();
							entity.setChatAccount(JidUtil.getAccountFromJID(msg
									.getFrom()));
							entity.setMsgType(ChatMsgEntity.COMMON_MESSAGE);
							entity.setMessage(GZIPUtil.uncompress(msg.getBody()));
							entity.setIsReaded(ChatMsgEntity.IS_NOT_READ);
							entity.setIsSended(ChatMsgEntity.SENDED_SUCCESS);
							entity.setMsgSourse(ChatMsgEntity.IS_COME_MSG);
							entity.setTime(TimeUtil.getCurrentMillisecond());
							entity.setPacketId(packet.getPacketID());
							entity.setChatType(ChatMsgEntity.PERSON_CHAT);
							mMessageQueue.putEntity(entity);
							return;
						}

						if (Type.groupchat == msg.getType()) {
							return;
						}
					}
				} catch (Exception e) {
					// SMACK silently discards exceptions dropped from
					// processPacket :(
					e.printStackTrace();
				}

			}
		};
		connection.addPacketListener(mMessageListener, filter);
	}

	private Thread mMessageSaveThread = new Thread(new Runnable() {
		@Override
		public void run() {
			while (true) {
				ChatMsgEntity entity = mMessageQueue.getEntity();
				mChatMsgDao.saveMsg(entity);
				mXmppService.processMessage(entity);
			}
		}
	});

	/**
	 * @Title: registerRosterListener
	 * @Description: 方法描述
	 */
	private void registerRosterListener() {
		// 获得用户的好友名单（花名册）
		mRoster = connection.getRoster();
		if (mRosterListener != null) {
			mRoster.removeRosterListener(mRosterListener);
		}
		mRosterListener = new RosterListener() {

			@Override
			public void entriesAdded(Collection<String> arg0) {// 添加操作，服务器还没有返回确认信息，返回确认信息后，会调用entriesUpdated方法
				getRosterThread();
			}

			@Override
			public void entriesDeleted(Collection<String> arg0) {// 删除操作，服务器还没有返回确认信息，返回确认信息后，会调用entriesUpdated方法
				getRosterThread();
			}

			@Override
			public void entriesUpdated(Collection<String> arg0) {
				getRosterThread();
			}

			@Override
			public void presenceChanged(Presence presence) {

			}
		};

		mRoster.addRosterListener(mRosterListener);
	}

	private void getRosterThread() {
		if (NetworkUtil.getNetworkState(mXmppService) != NetworkUtil.NETWORN_NONE) {
			if (mGetRosterThread != null) {
				mGetRosterThread.interrupt();
				mGetRosterThread = null;
			}
			if (mGetRosterThread == null) {
				mGetRosterThread = new Thread(new Runnable() {
					@Override
					public void run() {
						try {

							if (!mXmppService.isLogin()) {
								mXmppService.login();
							}
							Collection<RosterEntry> Entries = mXmppService
									.getEntities();
							mRosterEntryDao.clearTable();
							if (Entries != null && !Entries.isEmpty()) {
								Iterator<RosterEntry> iterator = Entries
										.iterator();
								while (iterator.hasNext()) {
									LocalRosterEntity roster = LocalRosterEntity
											.entryToEntity(iterator.next());
									mRosterEntryDao
											.saveOrUpdateRosterEntry(roster);
								}
							}
							handler.sendEmptyMessage(MyApplication.SUCCESS);
						} catch (Exception e) {
							e.printStackTrace();
							handler.sendEmptyMessage(MyApplication.EXCEPTION);
						}
					}
				});
				mGetRosterThread.start();
			}
		}
	}

	/**
	 * 
	 * 与服务器交互消息监听,发送消息需要回执，判断是否发送成功
	 * 
	 * @Title: initSendMsgListener
	 * @Description: 方法描述
	 */
	private void initSendMsgListener() {

		DeliveryReceiptManager manager = DeliveryReceiptManager
				.getInstanceFor(connection);
		manager.enableAutoReceipts();// 辅助方法，启动消息回执

		if (mReceiptReceivedListener != null) {
			manager.removeReceiptReceivedListener(mReceiptReceivedListener);
		}
		mReceiptReceivedListener = new ReceiptReceivedListener() {
			@Override
			public void onReceiptReceived(String arg0, String arg1, String arg2) {
				mLastReceivePacketTime = System.currentTimeMillis();
				// mChatMsgDao
				// .updateMsgSendStatus(arg2, ChatMsgEntity.GET_RECEIPT);
			}
		};
		manager.addReceiptReceivedListener(mReceiptReceivedListener);
	}

	@Override
	public void logout() throws XMPPException {
		if (!connection.isConnected()) {
			connection.connect();
		}
		if (mRosterListener != null) {
			connection.getRoster().removeRosterListener(mRosterListener);
		}
		if (mMessageListener != null) {
			connection.removePacketListener(mMessageListener);
		}
		if (mPongListener != null) {
			connection.removePacketListener(mPongListener);
		}
		if (connection.isAuthenticated()) {
			Presence presence = new Presence(Presence.Type.unavailable);
			connection.disconnect(presence);
			L.i(tag, "已登录");
		} else {
			L.i(tag, "未登录");
			connection.disconnect();
		}
	}

	@Override
	public boolean isAuthenticated() {
		return connection.isAuthenticated();
	}

	@Override
	public String searchAccount(String account) throws Exception {
		if (connection == null || !connection.isAuthenticated()) {
			return null;
		}
		UserSearchManager userSearchManger = new UserSearchManager(connection);
		Form searchForm = userSearchManger.getSearchForm("search."
				+ connection.getServiceName());
		Form answerForm = searchForm.createAnswerForm();
		// 查看协议 有时
		answerForm.setAnswer("Username", true);
		answerForm.setAnswer("search", account.trim());
		ReportedData resData = userSearchManger.getSearchResults(answerForm,
				"search." + connection.getServiceName());
		Iterator<Row> it = resData.getRows();
		Row row = null;
		while (it.hasNext()) {
			row = it.next();
			if (row.getValues("jid")
					.next()
					.toString()
					.equals(JidUtil.getJIDByAccount(account,
							connection.getServiceName()))) {
				return account;
			}
		}
		return null;
	}

	@Override
	public void addRosterItem(String account, String nickName)
			throws XMPPException {
		addRosterEntry(account, nickName);
	}

	/**
	 * @Title: addRosterEntry
	 * @Description: 方法描述
	 * @param user
	 * @param alias
	 * @param group
	 * @throws XMPPException
	 */
	private void addRosterEntry(String account, String nickName)
			throws XMPPException {
		if (connection == null || !connection.isAuthenticated()) {
			throw new XMPPException("未登录服务器");
		}
		mRoster = connection.getRoster();
		try {
			mRoster.createEntry(
					JidUtil.getJIDByAccount(account,
							connection.getServiceName()), nickName,
					new String[] { "Firends" });
			// Presence entity = new Presence();
			// entity.setFrom(JidUtil.getJIDByAccount(
			// MyApplication.getMyAccount(mXmppService),
			// connection.getServiceName()));
			// entity.setTo(JidUtil.getJIDByAccount(account,
			// connection.getServiceName()));
			// entity.setType(Presence.Type.subscribed);
			// sendPacket(entity);

		} catch (XMPPException e) {
			throw new XMPPException(e.getLocalizedMessage());
		}
	}

	@Override
	public void removeRosterItem(String account) throws XMPPException {
		if (connection == null || !connection.isAuthenticated()) {
			throw new XMPPException("未登录服务器");
		}
		mRoster = connection.getRoster();
		RosterEntry rosterEntry = mRoster.getEntry(JidUtil.getJIDByAccount(
				account, connection.getServiceName()));
		if (rosterEntry != null) {
			mRoster.removeEntry(rosterEntry);
		}
	}

	@Override
	public void renameRosterItem(String oldName, String newName)
			throws XMPPException {
		mRoster = connection.getRoster();
		RosterEntry rosterEntry = mRoster.getEntry(oldName);
		if (!(newName.length() > 0) || (rosterEntry == null)) {
			throw new XMPPException("JabberID to rename is invalid!");
		}
		rosterEntry.setName(newName);
	}

	@Override
	public void moveRosterItemToGroup(String userName, String groupName)
			throws XMPPException {
		mRoster = connection.getRoster();
		RosterGroup rosterGroup = getRosterGroup(groupName);
		RosterEntry rosterEntry = mRoster.getEntry(userName);

		Collection<RosterGroup> oldGroups = rosterEntry.getGroups();
		for (RosterGroup group : oldGroups) {
			try {
				group.removeEntry(rosterEntry);
			} catch (XMPPException e) {
				throw new XMPPException(e.getLocalizedMessage());
			}
		}

		if (groupName.length() == 0)
			return;
		else {
			try {
				rosterGroup.addEntry(rosterEntry);
			} catch (XMPPException e) {

			}
		}
	}

	private RosterGroup getRosterGroup(String groupName) {
		mRoster = connection.getRoster();
		RosterGroup rosterGroup = mRoster.getGroup(groupName);
		if ((groupName.length() > 0) && rosterGroup == null) {
			rosterGroup = mRoster.createGroup(groupName);
		}
		return rosterGroup;
	}

	@Override
	public void renameRosterGroup(String group, String newGroup) {
		mRoster = connection.getRoster();
		RosterGroup groupToRename = mRoster.getGroup(group);
		if (groupToRename == null) {
			return;
		}
		groupToRename.setName(newGroup);
	}

	@Override
	public void requestAuthorizationForRosterItem(String user) {
		Presence response = new Presence(Presence.Type.subscribe);
		response.setTo(user);
		connection.sendPacket(response);
	}

	@Override
	public void addRosterGroup(String group) {
		mRoster = connection.getRoster();
		mRoster.createGroup(group);
	}

	@Override
	public Message sendChatMessage(ChatMsgEntity entity) throws XMPPException {
		final Message newMessage = new Message(JidUtil.getJIDByAccount(
				entity.getChatAccount(), connection.getServiceName()),
				Message.Type.chat);
		newMessage.setBody(GZIPUtil.compress(entity.getMessage()));
		newMessage.setPacketID(entity.getPacketId());
		// 消息回执预处理
		// DeliveryReceiptManager.addDeliveryReceiptRequest(newMessage);
		connection.sendPacket(newMessage);
		return newMessage;
	}

	@Override
	public void sendOfflineMessages() {

	}

	@Override
	public void removeRosterGroup(String group) {

	}

	@Override
	public Collection<RosterEntry> getEntities() {

		if (connection == null || !connection.isAuthenticated()) {
			return null;
		}
		Roster roster = connection.getRoster();
		Collection<RosterEntry> dataCollection = roster.getEntries();
		return dataCollection;
	}

	@Override
	public void savePersonInfo(PersonInfoEntity info) throws XMPPException {
		if (connection == null || !connection.isAuthenticated()) {
			return;
		}
		VCard vCard = new VCard();
		JSON.toJSONString(info);
		// 用户信息
		vCard.setFirstName(JSON.toJSONString(info));

		// 手机信息
		PhoneInfoUtil util = new PhoneInfoUtil(mXmppService);
		vCard.setLastName(util.getAttributes());
		vCard.save(connection);
	}

	@Override
	public PersonInfoEntity getOurPersonInfo() throws XMPPException {
		if (connection == null || !connection.isAuthenticated()) {
			return null;
		}
		PersonInfoEntity info = new PersonInfoEntity();
		VCard vCard = new VCard();
		vCard.load(connection);
		info = JSON.parseObject(vCard.getFirstName(), PersonInfoEntity.class);
		return info;
	}

	@Override
	public PersonInfoEntity getPersonInfoByAccount(String account)
			throws XMPPException {
		if (connection == null || !connection.isAuthenticated()) {
			return null;
		}

		VCard vCard = new VCard();
		vCard.load(connection,
				JidUtil.getJIDByAccount(account, connection.getServiceName()));
		PersonInfoEntity info = new PersonInfoEntity();
		info = JSON.parseObject(vCard.getFirstName(), PersonInfoEntity.class);
		return info;
	}

	@Override
	public void sendPacket(Packet packet) {
		connection.sendPacket(packet);
	}

	@Override
	public LocalRosterEntity getRosterByAccount(String account) {
		mRoster = connection.getRoster();
		RosterEntry rosterEntry = mRoster.getEntry(JidUtil.getJIDByAccount(
				account, connection.getServiceName()));
		return LocalRosterEntity.entryToEntity(rosterEntry);
	}

	@Override
	public XMPPConnection getConnect() {
		if (connection != null) {
			return connection;
		} else {
			return null;
		}
	}

	@Override
	public Presence getPresenceOfAccount(String Account) {
		Roster roster = connection.getRoster();
		Presence presence = roster.getPresence(JidUtil.getJIDByAccount(Account,
				connection.getServiceName()));
		return presence;
	}

}
